{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c44da9e1-d76e-4956-8c19-9dade31e2bc5",
   "metadata": {},
   "source": [
    "# Intel® Extension for Scikit-learn Ridge Regression for IEEE-CIS Fraud Detection dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "963c5285-6470-474c-9550-6990029fa6a3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from timeit import default_timer as timer\n",
    "from sklearn import metrics\n",
    "from sklearn.model_selection import train_test_split\n",
    "import warnings\n",
    "from sklearn.datasets import fetch_openml\n",
    "from sklearn.preprocessing import LabelEncoder\n",
    "from IPython.display import HTML\n",
    "\n",
    "warnings.filterwarnings(\"ignore\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "421d17b2-a02f-464d-b196-9e46cd0bb396",
   "metadata": {},
   "source": [
    "### Download the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d0b94c65-bd7c-480e-bd56-e5adc711585f",
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset = fetch_openml(data_id=45955, as_frame=True)\n",
    "data = dataset.frame"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcb6b5bc-5a76-4741-b350-518cd9c43f9c",
   "metadata": {},
   "source": [
    "### Preprocessing\n",
    "Let's encode categorical features with LabelEncoder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7611e869-4079-4e6f-b0bf-9143bf7a8909",
   "metadata": {},
   "outputs": [],
   "source": [
    "data = dataset.frame\n",
    "\n",
    "# Simple imputation for missing values\n",
    "data = data.fillna(0)\n",
    "\n",
    "# Set the target variable\n",
    "x = data.drop(columns=['fraud'])\n",
    "y = data['fraud']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d21fbc59-1f27-4114-a54e-51a5263a5d31",
   "metadata": {},
   "outputs": [],
   "source": [
    "for col in ['used_pin_number', 'online_order', 'used_chip', 'repeat_retailer']:\n",
    "    le = LabelEncoder().fit(x[col])\n",
    "    x[col] = le.transform(x[col])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "3b8403b6-62c0-47da-992c-bc205817b54b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((900000, 7), (100000, 7), (900000,), (100000,))"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.1, random_state=0)\n",
    "x_train.shape, x_test.shape, y_train.shape, y_test.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "862647f0-e3cc-486f-b40f-c9d013b2b973",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import MinMaxScaler, StandardScaler\n",
    "\n",
    "scaler_x = MinMaxScaler()\n",
    "scaler_y = StandardScaler()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "7fabcc1c-1632-45bb-aa8e-cc6edd864a51",
   "metadata": {},
   "outputs": [],
   "source": [
    "y_train = y_train.to_numpy().reshape(-1, 1)\n",
    "y_test = y_test.to_numpy().reshape(-1, 1)\n",
    "\n",
    "scaler_x.fit(x_train)\n",
    "x_train = scaler_x.transform(x_train)\n",
    "x_test = scaler_x.transform(x_test)\n",
    "\n",
    "scaler_y.fit(y_train)\n",
    "y_train = scaler_y.transform(y_train).ravel()\n",
    "y_test = scaler_y.transform(y_test).ravel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c9e47e83-d09a-4243-a555-daba47a92140",
   "metadata": {},
   "source": [
    "### Patch original Scikit-learn with Intel® Extension for Scikit-learn\n",
    "Intel® Extension for Scikit-learn (previously known as daal4py) contains drop-in replacement functionality for the stock Scikit-learn package. You can take advantage of the performance optimizations of Intel® Extension for Scikit-learn by adding just two lines of code before the usual Scikit-learn imports:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "4fe10be8-83a0-4681-8ecc-6f8b09eb1e13",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Intel(R) Extension for Scikit-learn* enabled (https://github.com/uxlfoundation/scikit-learn-intelex)\n"
     ]
    }
   ],
   "source": [
    "from sklearnex import patch_sklearn\n",
    "\n",
    "patch_sklearn()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "60c6aa9b-748b-4a02-87b1-600d1130c4d8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Intel® extension for Scikit-learn time: 0.03 s'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.linear_model import Ridge\n",
    "\n",
    "params = {\n",
    "    \"alpha\": 0.3,\n",
    "    \"fit_intercept\": False,\n",
    "    \"random_state\": 0,\n",
    "    \"copy_X\": False,\n",
    "}\n",
    "start = timer()\n",
    "model = Ridge(random_state=0).fit(x_train, y_train)\n",
    "train_patched = timer() - start\n",
    "f\"Intel® extension for Scikit-learn time: {train_patched:.2f} s\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e3b5e2bc-a5fe-4f1b-90ab-b3119ad77b4b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Patched Scikit-learn MSE: 0.6899813655698377'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_predict = model.predict(x_test)\n",
    "mse_metric_opt = metrics.mean_squared_error(y_test, y_predict)\n",
    "f\"Patched Scikit-learn MSE: {mse_metric_opt}\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5c6010de-b52f-44af-b0f4-f76e8de128c5",
   "metadata": {},
   "source": [
    "### Train the same algorithm with original Scikit-learn\n",
    "In order to cancel optimizations, we use *unpatch_sklearn* and reimport the class Ridge"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "7dbf40f4-7cb6-4ad5-a5d1-a07793780b23",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearnex import unpatch_sklearn\n",
    "\n",
    "unpatch_sklearn()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "eb46f060-dbde-43a3-b173-6d1c02fd9b9c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Original Scikit-learn time: 0.12 s'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.linear_model import Ridge\n",
    "\n",
    "start = timer()\n",
    "model = Ridge(random_state=0).fit(x_train, y_train)\n",
    "train_unpatched = timer() - start\n",
    "f\"Original Scikit-learn time: {train_unpatched:.2f} s\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "6f55a543-d85a-4e76-95d1-4fef83b59d7e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Original Scikit-learn MSE: 0.6899813655698382'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_predict = model.predict(x_test)\n",
    "mse_metric_original = metrics.mean_squared_error(y_test, y_predict)\n",
    "f\"Original Scikit-learn MSE: {mse_metric_original}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "aa1355e0-b70c-448b-99d8-eee19f2b1f36",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<h3>Compare MSE metric of patched Scikit-learn and original</h3>MSE metric of patched Scikit-learn: 0.6899813655698377 <br>MSE metric of unpatched Scikit-learn: 0.6899813655698382 <br>Metrics ratio: 0.9999999999999992 <br><h3>With Scikit-learn-intelex patching you can:</h3><ul><li>Use your Scikit-learn code for training and prediction with minimal changes (a couple of lines of code);</li><li>Get comparable model quality</li><li>Get a <strong>3.7x</strong> speedup.</li></ul>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "HTML(\n",
    "    f\"<h3>Compare MSE metric of patched Scikit-learn and original</h3>\"\n",
    "    f\"MSE metric of patched Scikit-learn: {mse_metric_opt} <br>\"\n",
    "    f\"MSE metric of unpatched Scikit-learn: {mse_metric_original} <br>\"\n",
    "    f\"Metrics ratio: {mse_metric_opt/mse_metric_original} <br>\"\n",
    "    f\"<h3>With Scikit-learn-intelex patching you can:</h3>\"\n",
    "    f\"<ul>\"\n",
    "    f\"<li>Use your Scikit-learn code for training and prediction with minimal changes (a couple of lines of code);</li>\"\n",
    "    f\"<li>Get comparable model quality</li>\"\n",
    "    f\"<li>Get a <strong>{(train_unpatched/train_patched):.1f}x</strong> speedup.</li>\"\n",
    "    f\"</ul>\"\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
